/*
 * @Description:
 * @Author: Evan.Zhang
 * @Date: 2022-07-08 11:24:48
 * @LastEditTime: 2022-08-09 15:33:47
 * @LastEditors: Evan.Zhang
 * @Reference:
 */
import {
  getNoEffectObject,
  setObjectPrototype,
  getNetFileSync
} from "../lib"

// 原型
const prototype = getNoEffectObject();

/**
 * @description: 获取js文件
 * @return {*}
 * @param {*} uri
 */
prototype.asyncRequestJSfileByURI = async function (uri) {
  if (this.threadRunning) return;
  const res = await getNetFileSync(uri);
  if (res) {
    this.executeFileContent = res
    return true;
  } else {
    return false;
  }
}

/**
 * @description: 事件监听
 * @return {*}
 * @param {*} flag
 */
prototype.onStateChange = function (flag) {
  this.onStateChange && this.onStateChange(flag);
}


/**
 * @description: 通知线程开始根据参数执行
 * @return {*}
 */
prototype.execute = function (scope = {}, callback) {
  if (typeof scope !== "object") throw new TypeError("The thread 'scope' parameter must be a Object;");
  if (this.threadRunning) return undefined;
  if (!this.executeFileContent)
    throw new TypeError("noting can do!please execute 'asyncRequestJSfileByURI' function first, or execute function 'executeJSbyURI'!");
  this.onMessage = callback;
  // 通知线程开始初始化 执行对象
  this.worker.postMessage({
    jsFile: this.executeFileContent,
    args:scope,
  })
  return this.worker;
}

/**
 * @description: 根据js文件uri来运行
 * @return {*}
 * @param {*} uri
 * @param {*} scope
 */
prototype.executeByURI = function (uri, { scope = {},callback}) {
  if (this.threadRunning) return undefined;
  this.asyncRequestJSfileByURI(uri).then((success) => {
    console.log(success)
    if (!success) throw new Error(`take URI '${uri}' got some error... Thread not running/execute.`);
    return this.execute(scope,callback);
  })
}


/**
 * @description: 根据方法来运行（传入函数作用域为scope对象内容）
 * @return {*}
 * @param {*} func
 * @param {*} scope
 */
prototype.executeByFunction = function (func, { scope = {},callback}) {
  if (typeof func !== 'function') throw new TypeError("sorry,that's a invalid function object!");
  // 自执行
  this.executeFileContent = `(${func.toString()})()`
  return this.execute(scope,callback);
}

/**
 * @description: 分别 :路还很长，不能陪你了，撒由那拉！！
 * @return {*}
 */
prototype.parting = function () {
  // _THE_INSTANCE_CALLED_TERMINATE() = terminate()
  this.worker._THE_INSTANCE_CALLED_TERMINATE();
  delete this;
}


/**
 * @description: 获取全新空对象（绑定过原型）
 * @return {*}
 */
function createNewFullInstance() {
  return setObjectPrototype(
    getNoEffectObject(),
    prototype
  )
}

/**
 * @description: 初始化方法
 * @return {*}
 * @param {*} instance
 */
function instanceInitializer(instance) {
  instance.threadRunning = false;
  instance.id = `worker::${Math.random() * 1001001}${Date.now()}${Math.random() * 1001001}`

  // 绑定事件
  instance.worker.addEventListener('message',event => {
    const { TheThreadRunningState, TerminateThis } = event.data;
    if (TerminateThis) {
      // 若内部需要关闭线程，则关闭线程并释放此实例
      instance.parting()
    } else if (typeof TheThreadRunningState == "undefined") {
      // 不是发送状态信息即发送原生信息
      instance.onMessage && instance.onMessage(event.data);
    } else {
      // 否则为状态信息，更新状态
      instance.threadRunning = TheThreadRunningState;
      instance.onStateChange(TheThreadRunningState);
    }
  })
}

/**
 * @description: 保护实例
 * @return {*}
 */
function protectInstance({
  worker,
  instance
}) {
  // 修改terminate名称
  worker._THE_INSTANCE_CALLED_TERMINATE = worker.terminate
  worker.terminate = instance.parting.bind(instance)
}


/**
 * @description: 获取一个线程
 * @return {*}
 */
export default function createWorker() {
  // 预处理插件代码
  // @pre-parser:injectStringByFile('/source/core/web-worker/worker.js'):@pre-parser:injectTextBlobLink("workerURL")
  // @pre-parser:deleteThisLine
  const workerURL = undefined;

  const threadInstance = createNewFullInstance();

  threadInstance.worker = new window.Worker(workerURL);

  // 保护实例
  protectInstance({
    worker: threadInstance.worker,
    instance: threadInstance
  });
  // 初始化实例数据
  instanceInitializer(threadInstance);

  return threadInstance;
}